package com.rymcu.subject.controller;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.rymcu.subject.dto.RedisSubjectBo;
import com.rymcu.subject.dto.SubjectQuestionDTO;
import com.rymcu.subject.entity.Question;
import com.rymcu.subject.entity.SignCharData;
import com.rymcu.subject.entity.SubjectAnswerRecord;
import com.rymcu.subject.result.GlobalResult;
import com.rymcu.subject.result.GlobalResultGenerator;
import com.rymcu.subject.result.RespResult;
import com.rymcu.subject.service.SubjectAnswerRecordService;
import com.rymcu.subject.service.SubjectOptionService;
import com.rymcu.subject.service.SubjectQuestionService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.concurrent.TimeUnit;

import static java.util.stream.Collectors.toList;

/**
 * forestAnswerApi接口
 *
 * @author 🐛
 */
@Api(tags = "forestAnswerApi")
@Controller
@RequestMapping("/question")
public class QuestionController {

    private static final Logger logger = LoggerFactory.getLogger(QuestionController.class);
    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    private SubjectQuestionService subjectQuestionService;
    @Autowired
    private SubjectAnswerRecordService subjectAnswerRecordService;

    public static Map<String, Object> getAnswerRecordGlobalResult(PageInfo<SubjectQuestionDTO> pageInfo) {
        Map<String, Object> map = new HashMap<>(2);
        map.put("answerRecords", pageInfo.getList());
        Map<String, Object> pagination = new HashMap<>(4);
        pagination.put("pageSize", pageInfo.getPageSize());
        pagination.put("total", pageInfo.getTotal());
        pagination.put("answerTotal", pageInfo.getTotal());
        pagination.put("currentPage", pageInfo.getPageNum());
        map.put("pagination", pagination);
        return map;
    }

    /**
     * 查看答案
     */
    @ApiOperation("查看答案")
    @GetMapping("/show-answer/{sq-id:\\d+}")
    @ResponseBody
    public GlobalResult getAnswer(@PathVariable(name = "sq-id") Long sqId) {
        final Question question = this.subjectQuestionService.selectBySqId(sqId);
        if (question == null) {
            return GlobalResultGenerator.genErrorResult("该题不存在");
        }
        return GlobalResultGenerator.genSuccessResult(new RespResult("正确答案", true, question.getAnswer()));
    }

    /**
     * 1、答题的编号必须和redis内存储的此用户试题编号一致
     * 2、如果redis内获取到的答题记录不存在,直接返回,
     * 3、如果存在，判断答题标志，已答题则直接返回
     * 4、判断答题的试题编号是否和redis题号一致，不一致返回错误提示
     * 5、进行答题,并更新redis答题标志
     *
     * @param subjectAnswerRecord
     * @return
     */
    @PostMapping("/answer/everyday")
    @ResponseBody
    @ApiOperation("进行答题")
    @Transactional
    public GlobalResult answerEverydayQuestion(@RequestBody SubjectAnswerRecord subjectAnswerRecord) {
        if (subjectAnswerRecord == null || subjectAnswerRecord.getUserId() == null || subjectAnswerRecord.getUserId() < 0L) {
            return GlobalResultGenerator.genErrorResult("用户编号错误或传输数据异常");
        }
        RedisSubjectBo redisSubjectBo = (RedisSubjectBo) redisTemplate.opsForValue().get(subjectAnswerRecord.getUserId());
        final Date now = new Date();
        if (redisSubjectBo == null) {
            return GlobalResultGenerator.genErrorResult("服务异常，请刷新页面后再次尝试");
        }
        if (redisSubjectBo.isAnswerFlag()) {
            return GlobalResultGenerator.genErrorResult("今日已进行答题，不可重复进行答题签到");
        }

        if (redisSubjectBo.getSubjectId().compareTo(subjectAnswerRecord.getSubjectQuestionId()) != 0) {
            return GlobalResultGenerator.genErrorResult("试题编号不匹配，请稍后再来答题");
        }

        Calendar curDate = Calendar.getInstance();
        Calendar tomorrowDate = new GregorianCalendar(curDate.get(Calendar.YEAR), curDate.get(Calendar.MONTH), curDate.get(Calendar.DATE) + 1, 0, 0, 0);
        int second = (int) (tomorrowDate.getTimeInMillis() - curDate.getTimeInMillis()) / 1000;
        redisSubjectBo.setAnswerFlag(true);
        redisSubjectBo.setSubjectId(subjectAnswerRecord.getSubjectQuestionId());
        redisTemplate.opsForValue().set(subjectAnswerRecord.getUserId(), redisSubjectBo, second, TimeUnit.SECONDS);
        return this.doAnswer(subjectAnswerRecord);

    }

    /**
     * 每日一题or答题记录
     */
    @ApiOperation("查看答题记录or随机出题")
    @GetMapping("/record/{user-id:\\d+}")
    @ResponseBody
    public GlobalResult answerRecord(
            @PathVariable("user-id") long userId,
            @RequestParam(defaultValue = "0") Integer page,
            @RequestParam(defaultValue = "10") Integer rows
    ) {
        final Date now = new Date();
        // 从redis里面取出答题记录
        RedisSubjectBo redisSubjectBo = (RedisSubjectBo) redisTemplate.opsForValue().get(userId);
        List<SubjectQuestionDTO> subjectQuestionDtoList = new ArrayList<>();

        if (redisSubjectBo == null) {
            redisSubjectBo = new RedisSubjectBo();
            final boolean existsAnswerRecord = this.subjectAnswerRecordService.existsAnswerRecord(userId, now, true);
            redisSubjectBo.setAnswerFlag(existsAnswerRecord);

            if (!existsAnswerRecord) {
                redisSubjectBo.setSubjectId(this.subjectQuestionService.getNextIdByUserId(userId));
            }
            Calendar curDate = Calendar.getInstance();
            Calendar tomorrowDate = new GregorianCalendar(curDate.get(Calendar.YEAR), curDate.get(Calendar.MONTH), curDate.get(Calendar.DATE) + 1, 0, 0, 0);
            int second = (int) (tomorrowDate.getTimeInMillis() - curDate.getTimeInMillis()) / 1000;
            // 设置今天过期
            redisTemplate.opsForValue().set(userId, redisSubjectBo, second, TimeUnit.SECONDS);
        }

        if (redisSubjectBo.isAnswerFlag()) {
            subjectQuestionDtoList.addAll(subjectQuestionService.getAnswerRecord(userId, now, true));
        } else {
            subjectQuestionDtoList.add(subjectQuestionService.getById(redisSubjectBo.getSubjectId()));
        }

        final PageInfo pageInfo = new PageInfo(subjectQuestionDtoList);
        PageHelper.startPage(page, rows);
        final Map<String, Object> map = getAnswerRecordGlobalResult(pageInfo);
        map.put("notExists", !redisSubjectBo.isAnswerFlag());
        return GlobalResultGenerator.genSuccessResult(map);
    }

    /**
     * 签题图
     */
    @ApiOperation("签题图")
    @GetMapping("/charts/{user-id:\\d+}")
    @ResponseBody
    public GlobalResult listSignChartData(@PathVariable("user-id") long userId

    ) {

        if (userId == 0L) {
            return GlobalResultGenerator.genErrorResult("用户编号不能为空");
        }
        final Date now = new Date();
        final List<SignCharData> listSignChartData = this.subjectAnswerRecordService.listSignChartData(userId, now);
        final Map<String, Object> map = new HashMap<>(31);
        map.put("dataList", listSignChartData.stream().map(obj -> new Object[]{obj.getSysDate(), obj.getSignedDate(), obj.getSignedFlag()}).collect(toList()));
        map.put("now", now);
        return GlobalResultGenerator.genSuccessResult(map);
    }


    /**
     * 答题、插入答题记录
     *
     * @param subjectAnswerRecord
     * @return
     */
    private GlobalResult doAnswer(SubjectAnswerRecord subjectAnswerRecord) {
        final String answer = subjectAnswerRecord.getAnswer();
        final Long userId = subjectAnswerRecord.getUserId();
        subjectAnswerRecord.setCreatedTime(new Date());
        final long sqId = subjectAnswerRecord.getSubjectQuestionId();
        if (userId == null || userId == 0L) {
            return GlobalResultGenerator.genErrorResult("答题用户编号不能为空");
        }
        if (answer.isBlank()) {
            return GlobalResultGenerator.genErrorResult("格式错误");
        }

        final Question question = this.subjectQuestionService.selectBySqId(sqId);
        if (question == null) {
            return GlobalResultGenerator.genErrorResult("题库此题记录异常");
        }
        final boolean answerFlag = answer.equalsIgnoreCase(question.getAnswer());
        subjectAnswerRecord.setAnswerFlag(answerFlag);

        this.subjectAnswerRecordService.insertSelective(subjectAnswerRecord);
        return GlobalResultGenerator.genResult(true, answerFlag, answerFlag ? "回答正确" : "回答错误");
    }
}
